package be.ipl.finito.usercase;

import javax.ejb.EJBException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

import be.ipl.finito.domaine.Joueur;
import be.ipl.finito.domaine.Partie;
import be.ipl.finito.domaine.Partie.Etat;
import be.ipl.finito.exceptions.ArgumentInvalideException;
import be.ipl.finito.exceptions.JoueurDejaInscritException;
import be.ipl.finito.exceptions.JoueurExistantException;
import be.ipl.finito.exceptions.JoueurInExistantException;
import be.ipl.finito.exceptions.MotDePasseException;
import be.ipl.finito.exceptions.PartieException;
import be.ipl.finito.exceptions.PartieInExistanteException;
import be.ipl.finito.usecases.GestionJoueur;
import be.ipl.finito.usecases.GestionPartie;

public class TestGestionPartie {
	
	private Context jndi;

	private static GestionPartie gestionPartie;
	private static GestionJoueur gestionJoueur;

	private Partie partie = null;

	private Joueur michel;
	private Joueur olivier;
	private Joueur julien;

	@BeforeClass
	public void setUp() throws NamingException, MotDePasseException, JoueurExistantException {
		jndi = new InitialContext();
		gestionPartie = (GestionPartie) jndi
				.lookup("ejb:/FINITO_EJB/GestionPartieImpl!be.ipl.finito.usecases.GestionPartie");
		gestionJoueur = (GestionJoueur) jndi
				.lookup("ejb:/FINITO_EJB/GestionJoueurImpl!be.ipl.finito.usecases.GestionJoueur");
		try {
			michel = gestionJoueur.sInscrire("michou", "password", "password", "debacker", "michel",
				"michel.debacker@ipl.be");
		} catch(IllegalStateException ea) {
				
		}
		try {
			olivier = gestionJoueur.sInscrire("ollie", "password", "password", "choquet", "olivier",
				"olivier.choquet@ipl.be");
		} catch(IllegalStateException ea) {
				
		}
		try {
			julien = gestionJoueur.sInscrire("julien", "password", "password", "aaaaa", "Julien", "julien@qq.com");
		} catch(IllegalStateException ea) {
				
		}
	}
	
	@AfterMethod
	public void tearDown() throws ArgumentInvalideException {
		
	}

	@Test
	public void testCreerPartie() throws ArgumentInvalideException, PartieException, PartieInExistanteException {
		try {
			partie = gestionPartie.creerPartie("biereFight");
		} catch(IllegalStateException e) {
			
		}
		Assert.assertNotNull(this.gestionPartie.chercherPartie(partie.getId()));
	}

	@Test
	public void testCreerPartieDejaCreee() throws ArgumentInvalideException, PartieException {
		partie = this.gestionPartie.creerPartie("biereFight");
		Assert.assertNull(this.gestionPartie.creerPartie("biereFight"));
	}
	
	@Test
	public void testRejoindrePartieTerminee() throws ArgumentInvalideException, PartieInExistanteException, JoueurInExistantException, JoueurDejaInscritException, PartieException {
		partie = this.gestionPartie.creerPartie("biereFight");
		partie = this.gestionPartie.rejoindrePartie(partie.getId(), michel);
		partie = this.gestionPartie.commencerPartie(partie.getId(), olivier);
		//TODO
	}

	@Test
	public void testRejoindrePartieEnAttente()
			throws ArgumentInvalideException, PartieInExistanteException,
			JoueurInExistantException, JoueurDejaInscritException, PartieException {
		partie = this.gestionPartie.creerPartie("biereFight");
		partie = this.gestionPartie.rejoindrePartie(partie.getId(), michel);
		Assert.assertTrue(partie.getJoueurs().contains(michel));
	}
	
	@Test
	public void testRejoindrePartieEnCours() throws ArgumentInvalideException, PartieInExistanteException, JoueurInExistantException, JoueurDejaInscritException, PartieException {
		partie = this.gestionPartie.creerPartie("biereFight");
		this.gestionPartie.rejoindrePartie(partie.getId(), michel);
		this.gestionPartie.commencerPartie(partie.getId(), julien);
		Assert.assertNull(this.gestionPartie.rejoindrePartie(partie.getId(), olivier));
	}
	
	@Test
	public void testLancerPartie() throws ArgumentInvalideException, PartieInExistanteException, JoueurInExistantException, JoueurDejaInscritException, PartieException {
		partie = this.gestionPartie.creerPartie("biereFight");
		this.gestionPartie.rejoindrePartie(partie.getId(), michel);
		this.gestionPartie.rejoindrePartie(partie.getId(), olivier);
		this.gestionPartie.commencerPartie(partie.getId(), julien);
		Assert.assertTrue(partie.getEtat() == Etat.EN_COURS);
	}
	
	@Test
	public void testListerPartieEnAttente() throws ArgumentInvalideException, PartieException {
		partie = this.gestionPartie.creerPartie("biereFight");
		Assert.assertEquals(this.gestionPartie.listerPartiesEnAttente().size(), 1);
	}
	
	@Test
	public void testListerPartiesEnAttenteAvecPartieEnCours() throws ArgumentInvalideException, PartieInExistanteException, JoueurInExistantException, JoueurDejaInscritException, PartieException {
		partie = this.gestionPartie.creerPartie("biereFight");
		partie = this.gestionPartie.rejoindrePartie(partie.getId(), michel);
		this.gestionPartie.commencerPartie(partie.getId(), julien);
		Assert.assertEquals(this.gestionPartie.listerPartiesEnAttente().size(), 0);
	}
	
	@Test
	public void testListerParties() throws ArgumentInvalideException, PartieInExistanteException, JoueurInExistantException, JoueurDejaInscritException, PartieException {
		partie = this.gestionPartie.creerPartie("biereFight");
		partie = this.gestionPartie.rejoindrePartie(partie.getId(), michel);
		this.gestionPartie.commencerPartie(partie.getId(), julien);
		Assert.assertEquals(this.gestionPartie.listerParties().size(), 1);
	}

}
